<?php

namespace app\provider;

use zhanshop\App;
use zhanshop\Helper;
use zhanshop\client\Httpclient;

class AdEventUploadProvider
{
    /**
     * 组合精准查询条件
     * @param array $where
     * @return string
     */
    protected function whereRawOr(array $where)
    {
        $whereField = ['oaid', 'imei', 'android_id', 'mac', 'idfa', 'iddi'];
        $whereRaw = "";
        foreach ($where as $k => $v){
            if(in_array($k, $whereField)){
                $k = strval($k);
                $v = strval($v);
                if($v && strlen($v) >= 5){
                    $whereRaw .= $k.' = "'.addslashes($v).'" or ';
                }
            }
        }
        if(isset($where['oaid']) && $where['oaid']){
            $whereRaw .= 'oaid = "'.md5($where['oaid']).'" or ';
        }
        // 如果imei在的话匹配一下md5的值
        if(isset($where['imei']) && $where['imei']){
            $whereRaw .= 'imei = "'.md5($where['imei']).'" or ';
        }

        if(isset($where['android_id']) && $where['android_id']){
            $whereRaw .= 'android_id = "'.md5($where['android_id']).'" or ';
        }

        if(isset($where['mac']) && $where['mac']){
            $whereRaw .= 'mac = "'.md5($where['mac']).'" or ';
        }
        return rtrim($whereRaw, 'or ');
    }

    /**
     * 激活
     * @param string $app
     * @param string $platform
     * @param array $matchItem
     * @param array $data
     * @return array
     */
    private function activate(string $app, string $platform, array $matchItem, array $data = [])
    {
        $mateType = 'manual';
        $record = [];
        if(isset($matchItem['id']) && $matchItem['id']){
            $record = App::database()->table("ad_record")->where(['id' => $matchItem['id']])->find();
        }

        if($record == false){
            $where = [
                'app' => $app,
            ];
            $exactWhere = $this->whereRawOr($matchItem);

            if($exactWhere){
                $record = App::database()->table("ad_record")->where($where)->whereRaw($exactWhere)->order('id desc')->find();
                if($record){
                    if($matchItem['oaid'] && ($matchItem['oaid'] == $record['oaid'] || md5($matchItem['oaid']) == $record['oaid'])){
                        $mateType = 'oaid';
                    }elseif ($matchItem['imei'] && ($matchItem['imei'] == $record['imei'] || md5($matchItem['imei']) == $record['imei'])){
                        $mateType = 'imei';
                    }elseif ($matchItem['android_id'] && ($matchItem['android_id'] == $record['android_id'] || md5($matchItem['android_id']) == $record['android_id'])){
                        $mateType = 'android_id';
                    }elseif ($matchItem['mac'] && ($matchItem['mac'] == $record['mac'] || md5($matchItem['mac']) == $record['mac'])){
                        $mateType = 'mac';
                    }if($matchItem['idfa'] && $matchItem['idfa'] == $record['idfa']){
                        $mateType = 'idfa';
                    }if($matchItem['iddi'] && $matchItem['iddi'] == $record['iddi']){
                        $mateType = 'iddi';
                    }
                }
            }

            if($record == false && $matchItem['ipv4'] && $matchItem['ua']){
                $mateType = 'ipv4+ua';
                $record = App::database()->table("ad_record")->where($where)->where(['ipv4' => $matchItem['ipv4'], 'ua' => $matchItem['ua']])->order('id desc')->find();
            }

            if($record == false && $matchItem['ipv6'] && $matchItem['ua']){
                $mateType = 'ipv6+ua';
                $record = App::database()->table("ad_record")->where($where)->where(['ipv6' => $matchItem['ipv6'], 'ua' => $matchItem['ua']])->order('id desc')->find();
            }

            if($record == false && $matchItem['ipv4'] && $matchItem['unit_type']){
                $mateType = 'ipv4+unittype';
                $record = App::database()->table("ad_record")->where($where)->where(['ipv4' => $matchItem['ipv4']])->whereRaw('ua LIKE "%'.$matchItem['unit_type'].'%"')->order('id desc')->find();
            }

            if($record == false && $matchItem['ipv6'] && $matchItem['unit_type']){
                $mateType = 'ipv6+unittype';
                $record = App::database()->table("ad_record")->where($where)->where(['ipv6' => $matchItem['ipv6']])->whereRaw('ua LIKE "%'.$matchItem['unit_type'].'%"')->order('id desc')->find();
            }

            if($record == false && $matchItem['ipv4']){
                $mateType = 'ipv4';
                $record = App::database()->table("ad_record")->where($where)->where(['ipv4' => $matchItem['ipv4']])->order('id desc')->find();
            }

            if($record == false && $matchItem['ipv6']){
                $mateType = 'ipv6';
                $record = App::database()->table("ad_record")->where($where)->where(['ipv6' => $matchItem['ipv6']])->order('id desc')->find();
            }
            if($record == false && $matchItem['ipv4']){
                $mateType = 'ipv4-md5';
                $record = App::database()->table("ad_record")->where($where)->where(['ipv4' => md5($matchItem['ipv4'])])->order('id desc')->find();
            }
            if($record == false && $matchItem['ipv6']){
                $mateType = 'ipv6-md5';
                $record = App::database()->table("ad_record")->where($where)->where(['ipv6' => md5($matchItem['ipv6'])])->order('id desc')->find();
            }
        }
        $result = [0, ''];
        if($record){
            $platform = $record['platform'];
            $result = $this->$platform($app, 'activate', $mateType, $matchItem, $record, $data);
        }
        return $result;
    }
    /**
     * 广告上报
     * @param string $app
     * @param string $platform
     * @param string $event
     * @param array $matchItem
     * @param array $data
     * @return array
     */
    public function upload(string $app, string $platform, string $event, array $matchItem, array $data = [])
    {
        if($event == 'activate'){
            return $this->activate($app, $platform, $matchItem, $data);
        }else{
            $record = App::database()->table("ad_upload")->where(['app' => $app, 'uuid' => $matchItem['uuid'], 'upload_event' => 'activate'])->order('id desc')->find();
            $result = [0, ''];
            // 在激活的基础上去做后续的事件上报
            if($record){
                $platform = $record['platform'];
                $result = $this->$platform($app, $event, $record['mate_type'], ['uuid' => $matchItem['uuid']], $record, $data);
            }
            return $result;
        }
    }

    // 字节事件映射
    // 【activate: 激活, register: 注册, order: 下单, pay: 付费, uv: 页面访问, form: 提交表单, custom: 自定义】
    protected $byteEvent = [
        'activate' => 'active',
        'register' => 'active_register',
        'order' => 'in_app_order',
        'pay' => 'active_pay',
        'uv' => 'in_app_uv',
        'form' => 'form',
        'custom' => 'custom',
    ];
    /**
     * @param $app 所属APP
     * @param $event 所属事件
     * @param $mateType 匹配方式
     * @param $matchItem 匹配的参数
     * @param $record 匹配到的条目
     * @param $attach 额外参数
     * @return void
     */
    public function byte(string $app, string $event, string $mateType, array $matchItem, array $record, array $attach = [], bool $isRetry = false)
    {

        $gatewayUrl = 'https://analytics.oceanengine.com/api/v2/conversion';

        $params = json_decode($record['params'] ?? "", true);
        $matchType = 0;
        if($record['event'] == "click"){
            $matchType = 1;
        }elseif (strpos($record['event'], 'play') !== false){
            $matchType = 2;
        }
        $time = time();
        $param = [
            'event_type' => $this->byteEvent[$event] ?? 'custom',
            'context' => [
                'ad' => [
                    'callback' => $params['callback_param'] ?? '',
                    'match_type' => $matchType,
                ]
            ],
            'timestamp' => $time * 1000
        ];
        if($record['android_id'] ?? ''){
            $param['device'] = [
                "platform" => "android",
                "android_id" => $record['android_id']
            ];
        }elseif ($record['idfa'] ?? ''){
            $param['device'] = [
                "platform" => "ios",
                "idfv" => $record['idfa'] ?? ''
            ];
        }
        $result = (new Httpclient())->debug()->setHeader("Content-Type", "application/json")->request($gatewayUrl, "POST", json_encode($param));

        $upAid = $this->writeUpload($app, $event, $mateType, $matchItem, $record, $attach, $result, $isRetry);
        return [$upAid, 'byte'];
    }

    protected $xiaomiEvent = [
        'activate' => 'APP_ACTIVE',
        'register' => 'APP_REGISTER',
        'order' => 'APP_SHOP_ORDER',
        'pay' => 'APP_PAY',
        'uv' => 'APP_IPVUV',
        'form' => 'APP_ADDICTION',
        'custom' => 'APP_ADDICTION',
    ];

    /**
     * 小米广告事件上报
     * @param string $app
     * @param string $event
     * @param string $mateType
     * @param array $matchItem
     * @param array $record
     * @param array $attach
     * @return void
     */
    public function xiaomi(string $app, string $event, string $mateType, array $matchItem, array $record, array $attach = [], bool $isRetry = false)
    {
        $params = json_decode($record['params'] ?? "", true);
        $imei = strval($record['imei'] ?? '');
        $oaid = strval($record['oaid'] ?? '');
        $ua = strval($record['ua'] ?? '');
        $url = 'http://trail.e.mi.com/api/callback?callback='.($params['callback'] ?? "");


        $time = time();
        if($oaid && strlen($oaid) > 4){
            $url .= '&oaid='.$oaid;
        }

        if($imei && strlen($imei) > 4){
            $url .= '&imei='.$imei;
        }

        if($ua && strlen($ua) > 4){
            $uas = explode('@', $ua);
            $url .= '&client_ip='.$uas[0];
            $url .= '&ua='.urlencode($uas[1] ?? '');
        }
        $url .= '&conv_time='.($time * 1000).'&convType='.($this->xiaomiEvent[$event] ?? 'APP_ADDICTION');

        $result = (new Httpclient())->debug()->setHeader("Content-Type", "application/json")->request($url);

        $upAid = $this->writeUpload($app, $event, $mateType, $matchItem, $record, $attach, $result, $isRetry);
        return [$upAid, 'xiaomi'];
    }

    protected $vivoEvent = [
        'activate' => 'ACTIVATION',
        'register' => 'REGISTER',
        'order' => 'IN_APP_ORDER',
        'pay' => 'PAY',
        'add_screen' => 'ADD_SCREEN',
        'uv' => 'PAGE_VIEW',
        'form' => 'SUBMIT',
        'custom' => 'CUSTOM',
    ];
    /**
     * vivo广告事件上报
     * @param $app 所属APP
     * @param $event 所属事件
     * @param $mateType 匹配方式
     * @param $matchItem 匹配的参数
     * @param $record 匹配到的条目
     * @param $attach 额外参数
     * @return void
     */
    public function vivo(string $app, string $event, string $mateType, array $matchItem, array $record, array $attach = [], bool $isRetry = false)
    {
        $oauth = App::make(SnsTokenProvider::class)->getVivo($app);
        $params = json_decode($record['params'] ?? "", true);
        $timestamp = time() * 1000;
        $url = 'https://marketing-api.vivo.com.cn/openapi/v1/advertiser/behavior/upload?access_token='.($oauth['access_token'] ?? '').'&timestamp='.$timestamp.'&nonce='.Helper::getNonceStr().'&advertiser_id='.($record['account_id'] ?? '');

        $userId = $record['oaid'];
        $userIdType = "OAID";

        if(isset($record['imei']) && $record['imei'] && strlen($record['imei']) >= 15){
            $userIdType = 'IMEI';
            if(strlen($record['imei']) > 17){
                $userIdType = 'IMEI_MD5';
            }
            $userId = $record['imei'];
        }

        $httpclient = new Httpclient();
        $httpclient->setHeader("Content-Type", "application/json");
        $result = $httpclient->debug()->request($url, "POST", json_encode([
            'srcType' => $params['src_type'] ?? 'APP',
            'srcId' => $params['src_id'] ?? '',
            'pkgName' => $params['pkg_name'] ?? '',
            'dataFrom' => "1",
            'dataList' => [
                [
                    'userIdType' => $userIdType,
                    'userId' => $userId,
                    'cvType' => $this->vivoEvent[$event] ?? 'CUSTOM',
                    'cvTime' => $timestamp,
                    'requestId' => $params['requestid'] ?? "0",
                    'creativeId' => $params['creativeid'] ?? "0"
                ]
            ],
        ]));

        $upAid = $this->writeUpload($app, $event, $mateType, $matchItem, $record, $attach, $result, $isRetry);

        return [$upAid, 'vivo'];
    }

    protected $oppoEvent = [
        'activate' => 1,
        'register' => 2,
        'order' => 6,
        'pay' => 7,
        'uv' => 23,
        'form' => 23,
        'custom' => 23,
    ];

    /**
     * oppo广告事件上报
     * @param $app 所属APP
     * @param $event 所属事件
     * @param $mateType 匹配方式
     * @param $matchItem 匹配的参数
     * @param $record 匹配到的条目
     * @param $attach 额外参数
     * @return void
     */
    public function oppo(string $app, string $event, string $mateType, array $matchItem, array $record, array $attach = [], bool $isRetry = false)
    {
        $params = json_decode($record['params'] ?? "", true);
        $time = time();
        $data = [
            'timestamp' => $time * 1000,
            'pkg' => $params['bundle'] ?? '',
            'dataType' => $this->oppoEvent[$event] ?? 23,
            'channel' => 1,
            'type' => 0,
            'ascribeType' => 1,
            'adId' => $params['adid'] ?? '-1',
            'clientIp' => $params['ip'] ?? '',
        ];

        $url = 'https://api.ads.heytapmobi.com/api/uploadActiveData';

        $result = ['code' => 403, 'body' => '上报失败'];
        if($record['imei'] && strlen($record['imei']) > 6){
            $data['type'] = 1;
            $data['imei'] = openssl_encrypt($record['imei'], "AES-128-ECB",base64_decode('XGAXicVG5GMBsx5bueOe4w=='),0,"");
            $result = (new Httpclient())->setHeader('timestamp', strval($time * 1000))->setHeader('Content-Type', 'application/json')->setHeader('signature', md5(json_encode($data). $time * 1000 . 'e0u6fnlag06lc3pl'))->debug()->request($url, "POST", json_encode($data));
        }else{
            $data['ouId'] = openssl_encrypt($record['oaid'], "AES-128-ECB",base64_decode('XGAXicVG5GMBsx5bueOe4w=='),0,"");
            $result = (new Httpclient())->setHeader('timestamp', strval($time * 1000))->setHeader('Content-Type', 'application/json')->setHeader('signature', md5(json_encode($data). $time * 1000 . 'e0u6fnlag06lc3pl'))->debug()->request($url, "POST", json_encode($data));
        }

        $upAid = $this->writeUpload($app, $event, $mateType, $matchItem, $record, $attach, $result, $isRetry);

        return [$upAid, 'oppo'];
    }

    protected $huaweiEvent = [
        'activate' => '1',
        'register' => '7',
        'order' => '18',
        'pay' => '4',
        'uv' => '9',
        'form' => '5',
        'custom' => '101',
    ];

    public function huawei(string $app, string $event, string $mateType, array $matchItem, array $record, array $attach = [], bool $isRetry = false)
    {
        $oauth = App::make(SnsTokenProvider::class)->getHuawei($app);
        // 华为的要好好弄一下 首先广告检测里面的unique_id 换成imei
        $params = json_decode($record['params'] ?? "", true);
        $deviceIdType = 'OAID';
        $deviceId = $record['oaid'];
        if(($params['id_type'] ?? '') == '0'){
            $deviceIdType = 'IMEI_MD5';
            $deviceId = $record['imei'];
        }
        $param = [
            'actionType' => $this->huaweiEvent[$event] ?? '101',
            'actionTime' => time() * 1000,
            'appId' => strval($params['app_id'] ?? ''),
            'deviceIdType' => $deviceIdType,
            'deviceId' => $deviceId,
            'callBack' => $params['callback'] ?? '',
        ];

        $result = (new Httpclient())->setHeader("client_id", ($oauth['client_id'] ?? ''))->setHeader("Authorization", "Bearer ".($oauth['access_token'] ?? ''))->debug()->setHeader("Content-Type", "application/json")->debug()->request('https://connect-api.cloud.huawei.com/api/datasource/v1/track/activate', "POST", json_encode($param));

        $upAid = $this->writeUpload($app, $event, $mateType, $matchItem, $record, $attach, $result, $isRetry);

        return [$upAid, 'huawei'];
    }

    protected $honorEvent = [
        'activate' => 10001,
        'register' => 10002,
        'order' => 10007,
        'pay' => 10004,
        'uv' => 10005,
        'form' => 20001,
        'custom' => 50012,
    ];
    /**
     * 荣耀广告上报
     * @param string $app
     * @param string $event
     * @param string $mateType
     * @param array $matchItem
     * @param array $record
     * @param array $attach
     * @return void
     */
    public function honor(string $app, string $event, string $mateType, array $matchItem, array $record, array $attach = [], bool $isRetry = false)
    {
        $params = json_decode($record['params'] ?? "", true);
        $time = time();
        $param = [
            'trackId' => $params['track_id'] ?? '',
            'conversionId' => $this->honorEvent[$event] ?? 50012,
            'conversionTime' => $time * 1000,
            'advertiserId' => $params['advertiser_id'] ?? '',
            'oaid' => $record['oaid'] ?? '',
        ];

        $url = 'https://ads-drcn.platform.hihonorcloud.com/api/ad-tracking/v1/conversion?'.http_build_query($param);
        $result = (new Httpclient())->request($url);
        $upAid = $this->writeUpload($app, $event, $mateType, $matchItem, $record, $attach, $result, $isRetry);

        return [$upAid, 'honor'];
    }

    protected $baiduEvent = [
        'activate' => 'activate',
        'register' => 'register',
        'order' => 'ec_buy',
        'pay' => 'orders',
        'uv' => 'deep_page_access',
        'form' => 'user_defined',
        'custom' => 'user_defined',
    ];
    /**
     * 百度广告监测上报
     * @param string $app
     * @param string $event
     * @param string $mateType
     * @param array $matchItem
     * @param array $record
     * @param array $attach
     * @return void
     */
    public function baidu(string $app, string $event, string $mateType, array $matchItem, array $record, array $attach = [], bool $isRetry = false)
    {
        $params = json_decode($record['params'] ?? "", true);
        $extInfo = $params['ext_info'] ?? '';
        $akey = $params['akey'] ?? '';
        $idfa = $params['idfa'] ?? '';
        $imei = strval($record['imei'] ?? '');
        $oaid = strval($record['oaid'] ?? '');
        $mac = strval($record['mac'] ?? '');
        $androidId = strval($record['android_id'] ?? '');

        $time = time();

        $joinType = 'ip';
        if($oaid && strlen($oaid) > 4){
            $joinType = 'oaid';
        }else if($imei && strlen($imei) > 4){
            $joinType = 'imei';
        }else if($androidId && strlen($androidId) > 4){
            $joinType = 'android_id';
        }else if($idfa && strlen($idfa) > 4){
            $joinType = 'idfa';
        }else if($mac && strlen($mac) > 4){
            $joinType = 'mac';
        }
        $aType = $this->baiduEvent[$event] ?? 'user_defined';
        $url = 'http://ocpc.baidu.com/ocpcapi/cb/actionCb?a_type='.$aType.'&a_value=0&ext_info='.$extInfo;
        $url .= '&akey='.$akey.'&';
        $url .= '&a_time='.$time.'&';
        $url .= '&join_type='.$joinType.'&';
        $url .= '&idfa='.$idfa.'&';
        $url .= '&imei='.$imei.'&';
        $url .= '&oaid='.$oaid.'&';
        $url .= '&android_id='.$androidId;
        // 计算sign值
        $sign = md5($url . $akey);
        // 得到最终callback url
        $url = $url . '&sign=' . $sign;
        $result = (new Httpclient())->debug()->setHeader("Content-Type", "application/json")->request($url);

        $upAid = $this->writeUpload($app, $event, $mateType, $matchItem, $record, $attach, $result, $isRetry);

        return [$upAid, 'baidu'];
    }

    protected $kuaishouEvent = [
        'activate' => '1',
        'register' => '2',
        'order' => '14',
        'pay' => '3',
        'uv' => '12',
        'form' => '9',
        'custom' => '5',
    ];

    /**
     * 快手广告检测上报
     * @param string $app
     * @param string $event
     * @param string $mateType
     * @param array $matchItem
     * @param array $record
     * @param array $attach
     * @return array
     */
    public function kuaishou(string $app, string $event, string $mateType, array $matchItem, array $record, array $attach = [], bool $isRetry = false)
    {
        $params = json_decode($record['params'] ?? "", true);
        $callback = $params['callback'] ?? '';
        try {
            $query = parse_url($callback, PHP_URL_QUERY);
            parse_str($query, $querys);
            $callback = $querys['callback'];
        }catch (\Throwable $err){
            $callback = "";
        }

        $time = time();
        $aType = $this->kuaishouEvent[$event] ?? '5';
        $url = 'https://k.kuaishou.com/rest/web/task/debug/track/activate?event_type='.$aType.'&event_time='.$time.'000'.'&callback='.$callback;
        $result = (new Httpclient())->debug()->setHeader("Content-Type", "application/json")->request($url);

        $upAid = $this->writeUpload($app, $event, $mateType, $matchItem, $record, $attach, $result, $isRetry);
        return [$upAid, 'kuaishou'];
    }

    /**
     * 写入上报记录
     * @param string $app
     * @param string $event
     * @param string $mateType
     * @param array $matchItem
     * @param array $record
     * @param array $attach
     * @param array $result
     * @return float
     */
    public function writeUpload(string $app, string $event, string $mateType, array $matchItem, array $record, array $attach, array $result, bool $isRetry = false)
    {
        if($isRetry == true){
            $id = $record['id'] ?? 0;
            if($id && isset($record['upload_event'])){
                App::database()->model("ad_upload")->where(['id' => $id])->update(['status' => $result['code'], 'result' => substr($result['body'], 0, 500)]);
            }
            return $id;
        }
        $insertData = [
            'app' => $app,
            'platform' => $record['platform'] ?? '',
            'account_id' => $record['account_id'] ?? '',
            'adid' => $record['adid'] ?? '',
            'plan_id' => $record['plan_id'] ?? '',
            'creative_id' => $record['creative_id'] ?? '',
            'adname' => $record['adname'] ?? '',
            'event' => $record['event'],
            'oaid' => $record['oaid'] ?? '',
            'imei' => $record['imei'] ?? '',
            'android_id' => $record['android_id'] ?? '',
            'ipv4' => $record['ipv4'] ?? '',
            'ipv6' => $record['ipv6'] ?? '',
            'ua' => $record['ua'] ?? '',
            'os' => $record['os'] ?? '',
            'uuid' => $matchItem['uuid'] ?? '0',
            'params' => $record['params'] ?? '',
            'match_item' => json_encode($matchItem),
            'status' => $result['code'],
            'upload_event' => $event,
            'mate_type' => $mateType,
            'attach' => json_encode($attach),
            'result' => substr($result['body'], 0, 500),
            'create_time' => time(),
        ];
        return App::database()->model("ad_upload")->insertGetId($insertData);

    }
}